package com.gagakuai.utils;


import com.gagakuai.transport.channel.socket.InternetProtocolFamily;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.nio.channels.Channel;
import java.nio.channels.SocketChannel;
import java.nio.channels.spi.SelectorProvider;


public final class SelectorProviderUtil {


    public static Method findOpenMethod(String methodName) {
        try {
            return SelectorProvider.class.getMethod(methodName, java.net.ProtocolFamily.class);
        } catch (Throwable e) {
            // logger.debug("SelectorProvider.{}(ProtocolFamily) not available, will use default", methodName, e);
        }
        return null;
    }


    public static <C extends Channel> C newChannel(Method method, SelectorProvider provider,
                                                   InternetProtocolFamily family) throws IOException {
        /*
         *  Use the {@link SelectorProvider} to open {@link SocketChannel} and so remove condition in
         *  {@link SelectorProvider#provider()} which is called by each SocketChannel.open() otherwise.
         *
         *  See <a href="https://github.com/netty/netty/issues/2308">#2308</a>.
         */
        if (family != null && method != null) {
            try {
                @SuppressWarnings("unchecked")
                C channel = (C) method.invoke(
                        provider, ProtocolFamilyConverter.convert(family));
                return channel;
            } catch (InvocationTargetException e) {
                throw new IOException(e);
            } catch (IllegalAccessException e) {
                throw new IOException(e);
            }
        }
        return null;
    }

    private SelectorProviderUtil() {
    }
}
